home *** CD-ROM | disk | FTP | other *** search
- unit OpponentThread;
-
- interface
-
- uses SysUtils,Classes,syncobjs,Windows,Messages,Dialogs,
- //My Units
- BasicThread;
-
- type
- TOpponentThread=class(TBasicThread)
- private
- fHiddenWordThreadID:THandle;
- fMainFormHandle:THandle;
- fHiddenWordLength:integer;
- fPosition:integer;
- fLetter:Char;
- fWord:string;
- procedure ExecuteLoop;
- procedure PeekMessage;
- procedure Initialise;
- procedure WordLengthIs(const Len: integer);
- procedure GuessLetterAndPosition;
- procedure No;
- procedure Yes;
- function GotWord: boolean;
- protected
- procedure Execute;override;
- public
- constructor Create
- (CreateSuspended:Boolean;const HiddenWordThreadID,MainFormHandle:THandle;var ThreadID:THandle);
- destructor Destroy;override;
- end;
-
- implementation
-
- constructor TOpponentThread.Create
- (CreateSuspended:Boolean;const HiddenWordThreadID,MainFormHandle:THandle;var ThreadID:THandle);
- const
- cCreateSuspended=TRUE;
- begin
- fHiddenWordThreadID:=HiddenWordThreadID;
- fMainFormHandle:=MainFormHandle;
- inherited Create(cCreateSuspended);
- ThreadID:=self.ThreadID;//Lets acquire this value before the thread terminates.
- if not CreateSuspended then
- Resume;
- end;
-
- destructor TOpponentThread.Destroy;
- begin
- inherited Destroy;
- end;
-
- procedure TOpponentThread.Execute;
- var
- Msg:TMsg;
- begin
- try
- //Force a message queue for the thread to be created.
- Windows.PeekMessage(Msg,0,0,0,PM_NOREMOVE);
- Initialise;
- ExecuteLoop;
- except
- fException:=ExceptObject As Exception;
- Synchronize(ShowException);
- end;
- PostMessage(fMainFormHandle,WM_Signal_ThreadTerminating,ThreadID,0);
- end;
-
- procedure TOpponentThread.Initialise;
- begin
- fHiddenWordLength:=0;
- fWord:='';
- PostThreadMessage(fHiddenWordThreadID,WM_Signal_RequestWordLength,ThreadID,0);
- end;
-
- procedure TOpponentThread.ExecuteLoop;
- begin
- while not Terminated do
- begin
- try
- Windows.WaitMessage;
- //Note could use GetMessage but this wouldn't allow the WM_Quit to jump its
- //position in the queue.
- if PeekQuitMessage then
- exit;
- PeekMessage;
- except
- //Don't reraise the exception cos we require the loop to keep executing.
- on E:Exception do
- begin
- {Log Exception to Event Log}
- fException:=E;
- Synchronize(ShowException);
- end;
- end;
- end;
- end;
-
- procedure TOpponentThread.PeekMessage;
- var
- Msg:TMsg;
- begin
- while((not Terminated)and(Windows.PeekMessage(Msg,0,0,0,PM_Remove)))do
- begin
- case Msg.message of
- WM_QUIT:Terminate;
- WM_Signal_WordLengthIs:WordLengthIs(Msg.lParam);
- WM_Signal_Yes:Yes;
- WM_Signal_No:No;
- else
- exit;
- //Translates virtual-key messages into character messages
- //Not really required since the thread does not process any keyboard characters!!!
- //TranslateMessage(Msg);
- //Dispatches message to a window procedure with the window handle specified in the MSG structure
- //Note again the window handle will be null and no action taken.
- //DispatchMessage(Msg);
- end;
- end;
- end;
-
- procedure TOpponentThread.WordLengthIs(const Len:integer);
- begin
- fHiddenWordLength:=Len;
- fWord:=StringOfChar(' ',fHiddenWordLength);
- GuessLetterAndPosition;
- end;
-
- procedure TOpponentThread.GuessLetterAndPosition;
- var
- LP:LPARAM;
- iLetter:integer;
- begin
- fPosition:=Random(fHiddenWordLength)+1;//Uses binary bits 1,2,4,9,16=31
- fLetter:=Char(65+Random(26));// Uses binary bits 1,2,4,8,16,32,64=127
- iLetter:=Ord(fLetter);
- LP:=fPosition or (iLetter shl 5);
- PostThreadMessage(fHiddenWordThreadID,WM_Signal_RequestLetterUsedAtPosition,ThreadID,LP);
- end;
-
- procedure TOpponentThread.No;
- begin
- GuessLetterAndPosition;
- end;
-
- procedure TOpponentThread.Yes;
- begin
- fWord[fPosition]:=fLetter;
- if GotWord then
- begin
- PostMessage(fMainFormHandle,WM_Signal_ThreadGotAnswer,0,0);
- Terminate;
- end
- else
- GuessLetterAndPosition;
- end;
-
- function TOpponentThread.GotWord:boolean;
- begin
- Result:=Pos(' ',fWord)=0;
- end;
-
- end.
-
-